home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 002 / dbug / user.r < prev    next >
Text File  |  1995-03-17  |  26KB  |  935 lines

  1. .\"    @(#)user.r    1.10 12/20/85
  2. .\"
  3. .\"    DBUG (Macro Debugger Package) nroff source
  4. .\"
  5. .\"    nroff -mm user.r >user.t
  6. .\"
  7. .\" ===================================================
  8. .\"
  9. .\"    === Some sort of black magic, but I forget...
  10. .tr ~
  11. .\"    === Hyphenation control (1 = on)
  12. .\".nr Hy 1
  13. .\"    === Force all first level headings to start on new page
  14. .nr Ej 1
  15. .\"    === Set for breaks after headings for levels 1-3
  16. .nr Hb 3
  17. .\"    === Set for space after headings for levels 1-3
  18. .nr Hs 3
  19. .\"    === Set standard indent for one/half inch
  20. .nr Si 10
  21. .\"    === Set page header
  22. .PH "/DBUG User Manual/(preliminary)/\*(DT/"
  23. .\"    === Set page footer
  24. .PF "// - % - //"
  25. .\"    === Set page offset
  26. .\".po 0.60i
  27. .\"    === Set line length
  28. .\".ll 6.5i
  29. .TL
  30. D B U G
  31. .P 0
  32. C Program Debugging Package
  33. .P 0
  34. by
  35. .AU "Fred Fish"
  36. .AF ""
  37. .SA 1
  38. .\"    === All paragraphs indented.
  39. .nr Pt 1
  40. .AS 1
  41. This document introduces
  42. .I dbug ,
  43. a macro based C debugging
  44. package which has proven to be a very flexible and useful tool
  45. for debugging, testing, and porting C programs.
  46.  
  47. .P
  48. All of the features of the
  49. .I dbug
  50. package can be enabled or disabled dynamically at execution time.
  51. This means that production programs will run normally when
  52. debugging is not enabled, and eliminates the need to maintain two
  53. separate versions of a program.
  54.  
  55. .P
  56. Many of the things easily accomplished with conventional debugging
  57. tools, such as symbolic debuggers, are difficult or impossible with this
  58. package, and vice versa.
  59. Thus the
  60. .I dbug
  61. package should 
  62. .I not
  63. be thought of as a replacement or substitute for
  64. other debugging tools, but simply as a useful
  65. .I addition
  66. to the
  67. program development and maintenance environment.
  68.  
  69. .AE
  70. .MT 4
  71. .SK
  72. .B
  73. INTRODUCTION
  74. .R
  75.  
  76. .P
  77. Almost every program development environment worthy of the name
  78. provides some sort of debugging facility.
  79. Usually this takes the form of a program which is capable of
  80. controlling execution of other programs and examining the internal
  81. state of other executing programs.
  82. These types of programs will be referred to as external debuggers
  83. since the debugger is not part of the executing program.
  84. Examples of this type of debugger include the
  85. .B adb
  86. and
  87. .B sdb
  88. debuggers provided with the 
  89. .B UNIX\*F
  90. .FS
  91. UNIX is a trademark of AT&T Bell Laboratories.
  92. .FE
  93. operating system.
  94.  
  95. .P
  96. One of the problems associated with developing programs in an environment
  97. with good external debuggers is that developed programs tend to have 
  98. little or no internal instrumentation.
  99. This is usually not a problem for the developer since he is,
  100. or at least should be, intimately familiar with the internal organization,
  101. data structures, and control flow of the program being debugged.
  102. It is a serious problem for maintenance programmers, who
  103. are unlikely to have such familiarity with the program being
  104. maintained, modified, or ported to another environment.
  105. It is also a problem, even for the developer, when the program is
  106. moved to an environment with a primitive or unfamiliar debugger,
  107. or even no debugger.
  108.  
  109. .P
  110. On the other hand,
  111. .I dbug
  112. is an example of an internal debugger.
  113. Because it requires internal instrumentation of a program,
  114. and its usage does not depend on any special capabilities of
  115. the execution environment, it is always available and will
  116. execute in any environment that the program itself will
  117. execute in.
  118. In addition, since it is a complete package with a specific
  119. user interface, all programs which use it will be provided
  120. with similar debugging capabilities.
  121. This is in sharp contrast to other forms of internal instrumentation
  122. where each developer has their own, usually less capable, form
  123. of internal debugger.
  124. In summary,
  125. because 
  126. .I dbug
  127. is an internal debugger it provides consistency across operating
  128. environments, 
  129. and because it is available to all developers it provides
  130. consistency across all programs in the same environment.
  131.  
  132. .P
  133. The
  134. .I dbug
  135. package imposes only a slight speed penalty on executing
  136. programs, typically much less than 10 percent, and a modest size
  137. penalty, typically 10 to 20 percent.
  138. By defining a specific C preprocessor symbol both of these
  139. can be reduced to zero with no changes required to the
  140. source code.
  141.  
  142. .P
  143. The following list is a quick summary of the capabilities
  144. of the
  145. .I dbug
  146. package.
  147. Each capability can be individually enabled or disabled
  148. at the time a program is invoked by specifying the appropriate
  149. command line arguments.
  150. .SP 1
  151. .ML o 1i
  152. .LI
  153. Execution trace showing function level control flow in a
  154. semi-graphically manner using indentation to indicate nesting
  155. depth.
  156. .LI
  157. Output the values of all, or any subset of, key internal variables.
  158. .LI
  159. Limit actions to a specific set of named functions.
  160. .LI
  161. Limit function trace to a specified nesting depth.
  162. .LI
  163. Label each output line with source file name and line number.
  164. .LI
  165. Label each output line with name of current process.
  166. .LI
  167. Push or pop internal debugging state to allow execution with
  168. built in debugging defaults.
  169. .LI
  170. Redirect the debug output stream to standard output (stdout)
  171. or a named file.
  172. The default output stream is standard error (stderr).
  173. The redirection mechanism is completely independent of
  174. normal command line redirection to avoid output conflicts.
  175. .LE
  176.  
  177. .SK
  178. .B
  179. PRIMITIVE DEBUGGING TECHNIQUES
  180. .R
  181.  
  182. .P
  183. Internal instrumentation is already a familiar concept
  184. to most programmers, since it is usually the first debugging
  185. technique learned.
  186. Typically, "print\ statements" are inserted in the source
  187. code at interesting points, the code is recompiled and executed,
  188. and the resulting output is examined in an attempt to determine
  189. where the problem is.
  190.  
  191. The procedure is iterative, with each iteration yielding more
  192. and more output, and hopefully the source of the problem is
  193. discovered before the output becomes too large to deal with
  194. or previously inserted statements need to be removed.
  195. Figure 1 is an example of this type of primitive debugging
  196. technique.
  197. .DS I N
  198. .SP 2
  199. .so example1.r
  200. .SP 2
  201. .ll -5
  202. .ce
  203. Figure 1
  204. .ce
  205. Primitive Debugging Technique
  206. .ll +5
  207. .SP 2
  208. .DE
  209.  
  210. .P
  211. Eventually, and usually after at least several iterations, the
  212. problem will be found and corrected.
  213. At this point, the newly inserted print statements must be 
  214. dealt with.
  215. One obvious solution is to simply delete them all.
  216. Beginners usually do this a few times until they have to
  217. repeat the entire process every time a new bug pops up.
  218. The second most obvious solution is to somehow disable
  219. the output, either through the source code comment facility,
  220. creation of a debug variable to be switched on or off, or by using the
  221. C preprocessor.
  222. Figure 2 is an example of all three techniques.
  223. .DS I N
  224. .SP 2
  225. .so example2.r
  226. .SP 2
  227. .ll -5
  228. .ce
  229. Figure 2
  230. .ce
  231. Debug Disable Techniques
  232. .ll +5
  233. .SP 2
  234. .DE
  235.  
  236. .P
  237. Each technique has its advantages and disadvantages with respect
  238. to dynamic vs static activation, source code overhead, recompilation
  239. requirements, ease of use, program readability, etc.
  240. Overuse of the preprocessor solution quickly leads to problems with
  241. source code readability and maintainability when multiple 
  242. .B #ifdef
  243. symbols are to be defined or undefined based on specific types
  244. of debug desired.
  245. The source code can be made slightly more readable by suitable indentation
  246. of the 
  247. .B #ifdef
  248. arguments to match the indentation of the code, but
  249. not all C preprocessors allow this.
  250. The only requirement for the standard 
  251. .B UNIX
  252. C preprocessor is for the '#' character to appear
  253. in the first column, but even this seems
  254. like an arbitrary and unreasonable restriction.
  255. Figure 3 is an example of this usage.
  256. .DS I N
  257. .SP 2
  258. .so example3.r
  259. .SP 2
  260. .ll -5
  261. .ce
  262. Figure 3
  263. .ce
  264. More Readable Preprocessor Usage
  265. .ll +5
  266. .SP 2
  267. .DE
  268.  
  269. .SK
  270. .B
  271. FUNCTION TRACE EXAMPLE
  272. .R
  273.  
  274. .P
  275. We will start off learning about the capabilities of the
  276. .I dbug
  277. package by using a simple minded program which computes the
  278. factorial of a number.
  279. In order to better demonstrate the function trace mechanism, this
  280. program is implemented recursively.
  281. Figure 4 is the main function for this factorial program.
  282. .DS I N
  283. .SP 2
  284. .so main.r
  285. .SP 2
  286. .ll -5
  287. .ce
  288. Figure 4
  289. .ce
  290. Factorial Program Mainline
  291. .ll +5
  292. .SP 2
  293. .DE
  294.  
  295. .P
  296. The 
  297. .B main
  298. function is responsible for processing any command line
  299. option arguments and then computing and printing the factorial of
  300. each non-option argument.
  301. .P
  302. First of all, notice that all of the debugger functions are implemented
  303. via preprocessor macros.
  304. This does not detract from the readability of the code and makes disabling
  305. all debug compilation trivial (a single preprocessor symbol, 
  306. .B DBUG_OFF ,
  307. forces the macro expansions to be null).
  308. .P
  309. Also notice the inclusion of the header file
  310. .B dbug.h
  311. from the local header file directory.
  312. (The version included here is the test version in the dbug source
  313. distribution directory).
  314. This file contains all the definitions for the debugger macros, which
  315. all have the form 
  316. .B DBUG_XX...XX .
  317.  
  318. .P
  319. The 
  320. .B DBUG_ENTER 
  321. macro informs that debugger that we have entered the
  322. function named 
  323. .B main .
  324. It must be the very first "executable" line in a function, after
  325. all declarations and before any other executable line.
  326. The 
  327. .B DBUG_PROCESS
  328. macro is generally used only once per program to
  329. inform the debugger what name the program was invoked with.
  330. The
  331. .B DBUG_PUSH
  332. macro modifies the current debugger state by
  333. saving the previous state and setting a new state based on the
  334. control string passed as its argument.
  335. The
  336. .B DBUG_4
  337. macro is used to print the values of each argument
  338. for which a factorial is to be computed.
  339. The 
  340. .B DBUG_RETURN
  341. macro tells the debugger that the end of the current
  342. function has been reached and returns a value to the calling
  343. function.
  344. All of these macros will be fully explained in subsequent sections.
  345. .P
  346. To use the debugger, the factorial program is invoked with a command
  347. line of the form:
  348. .DS CB N
  349. factorial -#d:t 1 2 3
  350. .DE
  351. The 
  352. .B main
  353. function recognizes the "-#d:t" string as a debugger control
  354. string, and passes the debugger arguments ("d:t") to the 
  355. .I dbug
  356. runtime support routines via the
  357. .B DBUG_PUSH 
  358. macro.
  359. This particular string enables output from the
  360. .B DBUG_4
  361. macro with the 'd' flag and enables function tracing with the 't' flag.
  362. The factorial function is then called three times, with the arguments
  363. "1", "2", and "3".
  364.  
  365. .P
  366. Debug control strings consist of a header, the "-#", followed
  367. by a colon separated list of debugger arguments.
  368. Each debugger argument is a single character flag followed
  369. by an optional comma separated list of argments specific
  370. to the given flag.
  371. Some examples are:
  372. .DS CB N
  373. -#d:t:o
  374. -#d,in,out:f,main:F:L
  375. .DE
  376. Note that previously enabled debugger actions can be disabled by the
  377. control string "-#".
  378.  
  379. .P
  380. The definition of the factorial function, symbolized as "N!", is
  381. given by:
  382. .DS CB N
  383. N! = N * N-1 * ... 2 * 1
  384. .DE
  385. Figure 5 is the factorial function which implements this algorithm
  386. recursively.
  387. Note that this is not necessarily the best way to do factorials
  388. and error conditions are ignored completely.
  389. .DS I N
  390. .SP 2
  391. .so factorial.r
  392. .SP 2
  393. .ll -5
  394. .ce
  395. Figure 5
  396. .ce
  397. Factorial Function
  398. .ll +5
  399. .SP 2
  400. .DE
  401.  
  402. .P
  403. One advantage (some may not consider it so) to using the
  404. .I dbug
  405. package is that it strongly encourages fully structured coding
  406. with only one entry and one exit point in each function.
  407. Multiple exit points, such as early returns to escape a loop,
  408. may be used, but each such point requires the use of an
  409. appropriate 
  410. .B DBUG_RETURN
  411. or
  412. .B DBUG_VOID_RETURN
  413. macro.
  414.  
  415. .P
  416. To build the factorial program on a 
  417. .B UNIX
  418. system, compile and
  419. link with the command:
  420. .DS CB N
  421. cc -o factorial main.c factorial.c -ldbug
  422. .DE
  423. The "-ldbug" argument tells the loader to link in the
  424. runtime support modules for the
  425. .I dbug
  426. package.
  427. Executing the factorial program with a command of the form:
  428. .DS CB N
  429. factorial 1 2 3 4 5
  430. .DE
  431. generates the output shown in figure 6.
  432. .DS I N
  433. .SP 2
  434. .so output1.r
  435. .SP 2
  436. .ll -5
  437. .ce
  438. Figure 6
  439. .ce
  440. factorial 1 2 3 4 5
  441. .ll +5
  442. .SP 2
  443. .DE
  444.  
  445. .P
  446. Function level tracing is enabled by passing the debugger
  447. the 't' flag in the debug control string.
  448. Figure 7 is the output resulting from the command
  449. "factorial\ -#t:o\ 3\ 2".
  450. .DS I N
  451. .SP 2
  452. .so output2.r
  453. .SP 2
  454. .ll -5
  455. .ce
  456. Figure 7
  457. .ce
  458. factorial -#t:o 3 2
  459. .ll +5
  460. .SP 2
  461. .DE
  462.  
  463. .P
  464. Each entry to or return from a function is indicated by '>' for the
  465. entry point and '<' for the exit point, connected by
  466. vertical bars to allow matching points to be easily found
  467. when separated by large distances.
  468.  
  469. .P
  470. This trace output indicates that there was an initial call
  471. to factorial from main (to compute 2!), followed by
  472. a single recursive call to factorial to compute 1!.
  473. The main program then output the result for 2! and called the
  474. factorial function again with the second argument, 3.
  475. Factorial called itself recursively to compute 2! and 1!, then
  476. returned control to main, which output the value for 3! and exited.
  477.  
  478. .P
  479. Note that there is no matching entry point "main>" for the
  480. return point "<main" because at the time the 
  481. .B DBUG_ENTER
  482. macro was reached in main, tracing was not enabled yet.
  483. It was only after the macro
  484. .B DBUG_PUSH
  485. was executing that tracing became enabled.
  486. This implies that the argument list should be processed as early as
  487. possible since all code preceding the first call to
  488. .B DBUG_PUSH 
  489. is
  490. essentially invisible to 
  491. .B dbug
  492. (this can be worked around by
  493. inserted a temporary 
  494. .B DBUG_PUSH(argv[1])
  495. immediately after the
  496. .B DBUG_ENTER("main")
  497. macro.
  498.  
  499. .P
  500. One last note,
  501. the trace output normally comes out on the standard error.
  502. Since the factorial program prints its result on the standard
  503. output, there is the possibility of the output on the terminal
  504. being scrambled if the two streams are not synchronized.
  505. Thus the debugger is told to write its output on the standard
  506. output instead, via the 'o' flag character.
  507. Note that no 'o' implies the default (standard error), a 'o' 
  508. with no arguments means standard output, and a 'o' 
  509. with an argument means used the named file.
  510. I.E, "factorial\ -#t:o,logfile\ 3\ 2" would write the trace
  511. output in "logfile".
  512. Because of 
  513. .B UNIX
  514. implementation details, programs usually run
  515. faster when writing to stdout rather than stderr, though this
  516. is not a prime consideration in this example.
  517.  
  518. .SK
  519. .B
  520. USE OF DBUG_N MACROS
  521. .R
  522.  
  523. .P
  524. The mechanism used to produce "printf" style output is the
  525. .B DBUG_N
  526. macro, where
  527. .B N
  528. is replaced by the matching number of
  529. arguments to the macro.
  530. Unfortunately, the standard 
  531. .B UNIX
  532. C preprocessor does not allow macros
  533. to have variable number of arguments.
  534. If it did, then a single macro (such as DBUG_PRINTF) could replace all
  535. the 
  536. .B DBUG_N
  537. macros.
  538.  
  539. .P
  540. To allow selection of output from specific macros, the first argument
  541. to every 
  542. .B DBUG_N
  543. macro is a 
  544. .I dbug
  545. keyword.
  546. When this keyword appears in the argument list of the 'd' flag in
  547. a debug control string, as in "-#d,keyword1,keyword2,...:t",
  548. output from the corresponding macro is enabled.
  549. The default when there is no 'd' flag in the control string is to
  550. enable output from all 
  551. .B DBUG_N
  552. macros.
  553.  
  554. .P
  555. Typically, a program will be run once, with no keywords specified,
  556. to determine what keywords are significant for the current problem
  557. (the keywords are printed in the macro output line).
  558. Then the program will be run again, with the desired keywords,
  559. to examine only specific areas of interest.
  560.  
  561. .P
  562. The rest of the argument list to a 
  563. .B DBUG_N 
  564. is a standard printf style
  565. format string and one or more arguments to print.
  566. Note that no explicit newline is required at the end of the format string.
  567. As a matter of style, two or three small 
  568. .B DBUG_N
  569. macros are preferable
  570. to a single macro with a huge format string.
  571. Figure 8 shows the output for default tracing and debug.
  572. .DS I N
  573. .SP 2
  574. .so output3.r
  575. .SP 2
  576. .ll -5
  577. .ce
  578. Figure 8
  579. .ce
  580. factorial -#d:t:o 3
  581. .ll +5
  582. .SP 2
  583. .DE
  584.  
  585. .P
  586. The output from the 
  587. .B DBUG_N
  588. macro is indented to match the trace output
  589. for the function in which the macro occurs.
  590. When debugging is enabled, but not trace, the output starts at the left
  591. margin, without indentation.
  592.  
  593. .P
  594. To demonstrate selection of specific macros for output, figure
  595. 9 shows the result when the factorial program is invoked with
  596. the debug control string "-#d,result:o".
  597. .DS I N
  598. .SP 2
  599. .so output4.r
  600. .SP 2
  601. .ll -5
  602. .ce
  603. Figure 9
  604. .ce
  605. factorial -#d,result:o 4
  606. .ll +5
  607. .SP 2
  608. .DE
  609.  
  610. .P
  611. It is sometimes desirable to restrict debugging and trace actions
  612. to a specific function or list of functions.
  613. This is accomplished with the 'f' flag character in the debug
  614. control string.
  615. Figure 10 is the output of the factorial program when run with the
  616. control string "-#d:f,factorial:F:L:o".
  617. The 'F' flag enables printing of the source file name and the 'L'
  618. flag enables printing of the source file line number.
  619. .DS I N
  620. .SP 2
  621. .so output5.r
  622. .SP 2
  623. .ll -5
  624. .ce
  625. Figure 10
  626. .ce
  627. factorial -#d:f,factorial:F:L:o 3
  628. .ll +5
  629. .SP 2
  630. .DE
  631.  
  632. .P
  633. The output in figure 10 shows that the "find" macro is in file
  634. "factorial.c" at source line 8 and the "result" macro is in the same
  635. file at source line 12.
  636.  
  637. .SK
  638. .B
  639. SUMMARY OF MACROS
  640. .R
  641.  
  642. .P
  643. This section summarizes the usage of all currently defined macros
  644. in the 
  645. .I dbug
  646. package.
  647. The macros definitions are found in the user include file
  648. .B dbug.h
  649. from the standard include directory.
  650.  
  651. .SP 2
  652. .BL 20
  653. .LI DBUG_ENTER\ 
  654. Used to tell the runtime support module the name of the function
  655. being entered.
  656. The argument must be of type "pointer to character".
  657. The 
  658. DBUG_ENTER
  659. macro must precede all executable lines in the
  660. function just entered, and must come after all local declarations.
  661. Each 
  662. DBUG_ENTER
  663. macro must have a matching 
  664. DBUG_RETURN 
  665. or
  666. DBUG_VOID_RETURN
  667. macro 
  668. at the function exit points.
  669. DBUG_ENTER 
  670. macros used without a matching 
  671. DBUG_RETURN 
  672. or 
  673. DBUG_VOID_RETURN
  674. macro 
  675. will cause warning messages from the 
  676. .I dbug
  677. package runtime support module.
  678. .SP 1
  679. EX:\ DBUG_ENTER\ ("main");
  680. .SP 1
  681. .LI DBUG_RETURN\ 
  682. Used at each exit point of a function containing a 
  683. DBUG_ENTER 
  684. macro
  685. at the entry point.
  686. The argument is the value to return.
  687. Functions which return no value (void) should use the 
  688. DBUG_VOID_RETURN
  689. macro.
  690. It 
  691. is an error to have a 
  692. DBUG_RETURN 
  693. or 
  694. DBUG_VOID_RETURN 
  695. macro in a function
  696. which has no matching 
  697. DBUG_ENTER 
  698. macro, and the compiler will complain
  699. if the macros are actually used (expanded).
  700. .SP 1
  701. EX:\ DBUG_RETURN\ (value);
  702. .br
  703. EX:\ DBUG_VOID_RETURN;
  704. .SP 1
  705. .LI DBUG_PROCESS\ 
  706. Used to name the current process being executed.
  707. A typical argument for this macro is "argv[0]", though
  708. it will be perfectly happy with any other string.
  709. .SP 1
  710. EX:\ DBUG_PROCESS\ (argv[0]);
  711. .SP 1
  712. .LI DBUG_PUSH\ 
  713. Sets a new debugger state by pushing the current
  714. .B dbug
  715. state onto an
  716. internal stack and setting up the new state using the debug control
  717. string passed as the macro argument.
  718. The most common usage is to set the state specified by a debug
  719. control string retrieved from the argument list.
  720. Note that the leading "-#" in a debug control string specified
  721. as a command line argument must
  722. .B not
  723. be passed as part of the macro argument.
  724. The proper usage is to pass a pointer to the first character
  725. .B after
  726. the "-#" string.
  727. .SP 1
  728. EX:\ DBUG_PUSH\ (\&(argv[i][2]));
  729. .br
  730. EX:\ DBUG_PUSH\ ("d:t");
  731. .br
  732. EX:\ DBUG_PUSH\ ("");
  733. .SP 1
  734. .LI DBUG_POP\ 
  735. Restores the previous debugger state by popping the state stack.
  736. Attempting to pop more states than pushed will be ignored and no
  737. warning will be given.
  738. The 
  739. DBUG_POP 
  740. macro has no arguments.
  741. .SP 1
  742. EX:\ DBUG_POP\ ();
  743. .SP 1
  744. .LI DBUG_FILE\ 
  745. The 
  746. DBUG_FILE 
  747. macro is used to do explicit I/O on the debug output
  748. stream.
  749. It is used in the same manner as the symbols "stdout" and "stderr"
  750. in the standard I/O package.
  751. .SP 1
  752. EX:\ fprintf\ (DBUG_FILE,\ "Doing my own I/O!\n");
  753. .SP 1
  754. .LI DBUG_EXECUTE\ 
  755. The DBUG_EXECUTE macro is used to execute any arbitrary C code.
  756. The first argument is the debug keyword, used to trigger execution
  757. of the code specified as the second argument.
  758. This macro must be used cautiously because, like the 
  759. DBUG_N 
  760. macros,
  761. it is automatically selected by default whenever the 'd' flag has
  762. no argument list (I.E., a "-#d:t" control string).
  763. .SP 1
  764. EX:\ DBUG_EXECUTE\ ("abort",\ abort\ ());
  765. .SP 1
  766. .LI DBUG_N\ 
  767. Used to do printing via the "fprintf" library function on the
  768. current debug stream,
  769. DBUG_FILE.
  770. N may currently be a number in the range 2-5, and specifies the
  771. number of arguments in the corresponding macro.
  772. The first argument is a debug keyword, the second is a format string,
  773. and the remaining arguments, if any, are the values to be printed.
  774. .SP 1
  775. EX:\ DBUG_2\ ("eof",\ "end\ of\ file\ found");
  776. .br
  777. EX:\ DBUG_3\ ("type","type\ is\ %x", type);
  778. .br
  779. EX:\ DBUG_4\ ("stp", "%x\ ->\ %s", stp, stp\ ->\ name);
  780. .LI DBUG_SETJMP\ 
  781. Used in place of the setjmp() function to first save the current
  782. debugger state and then execute the standard setjmp call.
  783. This allows to the debugger to restore it's state when the
  784. DBUG_LONGJMP macro is used to invoke the standard longjmp() call.
  785. Currently all instances of DBUG_SETJMP must occur within the
  786. same function and at the same function nesting level.
  787. .SP 1
  788. EX:\ DBUG_SETJMP\ (env);
  789. .LI DBUG_LONGJMP\ 
  790. Used in place of the longjmp() function to first restore the
  791. previous debugger state at the time of the last DBUG_SETJMP
  792. and then execute the standard longjmp() call.
  793. Note that currently all DBUG_LONGJMP macros restore the state
  794. at the time of the last DBUG_SETJMP.
  795. It would be possible to maintain separate DBUG_SETJMP and DBUG_LONGJMP
  796. pairs by having the debugger runtime support module use the first
  797. argument to differentiate the pairs.
  798. .SP 1
  799. EX:\ DBUG_LONGJMP\ (env,val);
  800. .LE
  801.  
  802. .SK
  803. .B
  804. DEBUG CONTROL STRING
  805. .R
  806.  
  807. .P
  808. The debug control string is used to set the state of the debugger
  809. via the 
  810. .B DBUG_PUSH 
  811. macro.
  812. This section summarizes the currently available debugger options
  813. and the flag characters which enable or disable them.
  814. Argument lists enclosed in '[' and ']' are optional.
  815. .SP 2
  816. .BL 22
  817. .LI d[,keywords]
  818. Enable output from macros with specified keywords.
  819. A null list of keywords implies that all keywords are selected.
  820. .LI D[,time]
  821. Delay for specified time after each output line, to let output drain.
  822. Time is given in tenths of a second (value of 10 is one second).
  823. Default is zero.
  824. .LI f[,functions]
  825. Limit debugger actions to the specified list of functions.
  826. A null list of functions implies that all functions are selected.
  827. .LI F
  828. Mark each debugger output line with the name of the source file
  829. containing the macro causing the output.
  830. .LI L
  831. Mark each debugger output line with the source file line number of
  832. the macro causing the output.
  833. .LI n
  834. Mark each debugger output line with the current function nesting depth.
  835. .LI N
  836. Sequentially number each debugger output line starting at 1.
  837. This is useful for reference purposes when debugger output is
  838. interspersed with program output.
  839. .LI o[,file]
  840. Redirect the debugger output stream to the specified file.
  841. The default output stream is stderr.
  842. A null argument list causes output to be redirected to stdout.
  843. .LI p[,processes]
  844. Limit debugger actions to the specified processes.
  845. A null list implies all processes.
  846. This is useful for processes which run child processes.
  847. Note that each debugger output line can be marked with the name of
  848. the current process via the 'P' flag.
  849. The process name must match the argument passed to the
  850. .B DBUG_PROCESS
  851. macro.
  852. .LI P
  853. Mark each debugger output line with the name of the current process.
  854. Most useful when used with a process which runs child processes that
  855. are also being debugged.
  856. Note that the parent process must arrange for the debugger control
  857. string to be passed to the child processes.
  858. .LI r
  859. Used in conjunction with the 
  860. .B DBUG_PUSH 
  861. macro to reset the current
  862. indentation level back to zero.
  863. Most useful with 
  864. .B DBUG_PUSH 
  865. macros used to temporarily alter the
  866. debugger state.
  867. .LI t[,N]
  868. Enable function control flow tracing.
  869. The maximum nesting depth is specified by N, and defaults to
  870. 200.
  871. .LE
  872. .SK
  873. .B
  874. HINTS AND MISCELLANEOUS
  875. .R
  876.  
  877. .P
  878. One of the most useful capabilities of the 
  879. .I dbug 
  880. package is to compare the executions of a given program in two
  881. different environments.
  882. This is typically done by executing the program in the environment
  883. where it behaves properly and saving the debugger output in a
  884. reference file.
  885. The program is then run with identical inputs in the environment where 
  886. it misbehaves and the output is again captured in a reference file.
  887. The two reference files can then be differentially compared to
  888. determine exactly where execution of the two processes diverges.
  889.  
  890. .P
  891. A related usage is regression testing where the execution of a current
  892. version is compared against executions of previous versions.
  893. This is most useful when there are only minor changes.
  894.  
  895. .P
  896. It is not difficult to modify an existing compiler to implement
  897. some of the functionality of the 
  898. .I dbug
  899. package automatically, without source code changes to the
  900. program being debugged.
  901. In fact, such changes were implemented in a version of the
  902. Portable C Compiler by the author in less than a day.
  903. However, it is strongly encouraged that all newly
  904. developed code continue to use the debugger macros
  905. for the portability reasons noted earlier.
  906. The modified compiler should be used only for testing existing
  907. programs.
  908.  
  909. .SK
  910. .B
  911. CAVEATS
  912. .R
  913.  
  914. .P
  915. The 
  916. .I dbug
  917. package works best with programs which have "line\ oriented"
  918. output, such as text processors, general purpose utilities, etc.
  919. It can be interfaced with screen oriented programs such as
  920. visual editors by redefining the appropriate macros to call
  921. special functions for displaying the debugger results.
  922. Of course, this caveat is not applicable if the debugger output
  923. is simply dumped into a file for post-execution examination.
  924.  
  925. .P
  926. Programs which use memory allocation functions other than
  927. .B malloc
  928. will usually have problems using the standard
  929. .I dbug
  930. package.
  931. The most common problem is multiply allocated memory.
  932. .SP 2
  933. .DE
  934. .CS
  935.